package intermouse;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.zip.DataFormatException;

/**
 * @author Sőre András
 * @version 1.0
 * @since 2013-04-16
 * 
 * A main függvény által küldött command sztringek értelmezéséért és végrehajtásáért felelős osztály. 
 */
public class TestCommandParser {
	
	
	static BufferedWriter writer = null;
	
	/**
	 * @param s
	 * Kiír a standard outputra.
	 */
	static void print(String s){
		System.out.println(s);
	}

	/**
	 * @param s
	 * Kiír a standard outputra, és ha van kimeneti fájlnév, akkor oda is.
	 */
	static void log(String s){
		System.out.println(s);
		if(writer!=null){
		try {
			writer.write(s);
			writer.newLine();
		} catch (IOException e) {
			System.out.print("cannot write to file!");
			e.printStackTrace();
		}
		}
	}
	
	/**
	 * @param coordString
	 * @return
	 * @throws NumberFormatException
	 * Visszad koordinátákat int tömb formában egy sztringből.
	 */
	static int[] getCoordinates(String coordString) throws NumberFormatException{
		String[] numberStrings=null;
		try {
			numberStrings=coordString.substring(1, coordString.length()-1).split(",");
		} catch (IndexOutOfBoundsException e) {}
		
		if(numberStrings!=null && numberStrings.length==2){
			int numbers[]=new int[]{Integer.parseInt(numberStrings[0]),Integer.parseInt(numberStrings[1])};
			if(0<=numbers[0] && numbers[0]<=39 && 0<=numbers[1] && numbers[1]<=59)
			return numbers;
		}
		else 
			throw new NumberFormatException();
		return null;
	}
	

	/**
	 * @param command
	 * @param level
	 * Feltördeli és értelmezi a paraméterként kapott sztringet, és végrehajtja a paraméterként kapott Level-en.
	 */
	static void interpret(String command, Level level){
		
		String[] commands = new String[1];

		commands = command.split(" ");
		
//			A parancsok értelmezése a szavak száma alapján csoportosítva
			if(commands.length==1){
				if(commands[0].equals("exit")){
					print("exiting...");
					System.exit(0);
				}
				else if(commands[0].equals(""))
					print("awaiting orders ;)");
				else if(commands[0].equals("init")){
					level.init();
					log("Level is now replaced with an init’d one.");
					}
				else
					print("invalid input >:[");
			}
			else if(commands.length==2){
				if(commands[0].equals("step") ){
					try {
						int number = Integer.parseInt(commands[1]);
						for(int i=0; i<number; i++)
							level.makeStep();
							print("Made " + number + " steps.");
					} catch (NumberFormatException e) {
						print("invalid number!");
					}
				}
				else if(commands[0].equals("showobjects")){
					try {
						int[] coords = getCoordinates(commands[1]);
						for(FieldObject i : level.fields.get(coords[0]*60+coords[1]).obj)
						log("Object is a(n) "+ i.getClass().getSimpleName() +" at"+" ("+coords[0]+","+coords[1]+").");
					} catch (NumberFormatException e) {
						print("invalid coordinates!");
					}
				}
				else
					print("invalid input >:[");
			}
			else if(commands.length==3){
				if(commands[0].equals("spawn")){
					
					try {
						int[] coords = getCoordinates(commands[2]);
						Field f=level.fields.get(coords[0]*60+coords[1]);
						
						switch(commands[1]){
						case "Ant": Ant ant=new Ant(); 
							ant.setField(f);
							level.addAnt(ant);
						break;
						case "AntEater":
							//A malíciózuslistában is kéne tárolni?
							new AntEater().setField(f); break;
						case "AntHill":	new AntHill().setField(f); break;
						case "AntLion": new AntLion().setField(f); break;
						case "Food": new Food().setField(f); break;
						case "Poison": new Poison().setField(f); break;
						case "Stone": new Stone().setField(f); break;
						case "Water": new Water().setField(f); break;
						
						case "AntSmell": f.addSmell(new AntSmell()); break;
						case "FoodSmell": f.addSmell(new FoodSmell()); break;
						default: throw new DataFormatException("invalid classname!");	
						}
						log("Spawned "+ commands[1] + " at" + " ("+coords[0]+","+coords[1]+")." );
					} catch (NumberFormatException e) {
						print("invalid coordinates!");
					}catch(DataFormatException e){
						print(e.getMessage());
					}
				}
				else if(commands[0].equals("spray")){
					try {
						int[] coords = getCoordinates(commands[2]);
						
						if(commands[1].equals("deodorant")){
							level.fields.get(coords[0]*60+coords[1]).applyAntDeodorant(3);
						}
						else if(commands[1].equals("killer"))
							level.addPoison(level.fields.get(coords[0]*60+coords[1]));
						else
							throw new DataFormatException("invalid spray type!");
						
						log("Used "+ commands[1]+" at" + " ("+coords[0]+","+coords[1]+").");
						
					} catch (NumberFormatException e) {
						print("invalid coordinates!");
					} catch (DataFormatException e) {
						print(e.getMessage());
					}
				}
				else
					print("invalid input >:[");
			}
			else if(commands.length==4){
				if(commands[0].equals("move")){
					
					try {
						int[] targetCoords = getCoordinates(commands[2]);
						int[] coords = getCoordinates(commands[2]);
						
						switch (commands[3]) {
						case "N":
							if (targetCoords[0] % 2 == 1)
								targetCoords[0]--;
							else {
								targetCoords[0]--;
								targetCoords[1]++;
							}
							break;
						case "NE":
							targetCoords[1]++;
							break;
						case "SE":
							if (targetCoords[0] % 2 == 1)
								targetCoords[0]++;
							else {
								targetCoords[0]++;
								targetCoords[1]++;
							}
							break;
						case "S":
							if (targetCoords[0] % 2 == 1) {
								targetCoords[0]++;
								targetCoords[1]--;
							} else
								targetCoords[0]++;
							break;
						case "SW":
							if (targetCoords[0] % 2 == 1)
								targetCoords[1]--;
							break;
						case "NW":
							if (targetCoords[0] % 2 == 1) {
								targetCoords[0]--;
								targetCoords[1]--;
							} else
								targetCoords[0]--;
							break;
						default:
							throw new DataFormatException("invalid direction!");
						}
						
						if (!(0 <= targetCoords[0] && targetCoords[0] <= 39
								&& 0 <= targetCoords[1] && targetCoords[1] <= 59))
							throw new DataFormatException("invalid direction!");
						
						
						ArrayList<Field> tmp=new ArrayList<Field>(level.fields
								.get(coords[0]* 60 + coords[1]).getAdjacentFields());
						
						Iterator<Field> f=level.fields.get(coords[0]* 60 + coords[1])
								.getAdjacentFields().iterator();
						
						while(f.hasNext()){
							if(f.next()!=level.fields.get(targetCoords[0]* 60 + targetCoords[1]))
								f.remove();
						}
						
						//ListIterator<FieldObject> i=level.fields.get(coords[0]* 60 + coords[1]).obj.listIterator(0);
						
						Ant testAnt=null;
						AntEater testAntEater=null;
						
						switch (commands[1]) {
						case "Ant":
							for(FieldObject i : level.fields.get(coords[0]* 60 + coords[1]).obj)	
								if(i.getClass()==Ant.class){
									testAnt = (Ant)i;
									testAnt.beginRound();
								}
							break;
						case "AntEater":
							for(FieldObject i : level.fields.get(coords[0]* 60 + coords[1]).obj)	
								if(i.getClass()==AntEater.class){
									AntEater antEater = (AntEater)i;
									antEater.beginRound();
								}
														
							break;
//						case "Stone":
//							while(i.hasNext())
//								try {
//									Stone stone = (Stone)i.next();
////									stone.???
//								} catch (ClassCastException e) { 
//									print(e.getMessage());
//								}				 
//							break;
						default: print("invalid classname!");
							         break;
						}				
					level.fields.get(coords[0]* 60 + coords[1])
					.getAdjacentFields().clear();
					
					f = tmp.iterator();
					while(f.hasNext())
						level.fields.get(coords[0]* 60 + coords[1])
						.getAdjacentFields().add(f.next());
					
					if(testAnt==null && testAntEater==null)
						throw new DataFormatException("FieldObject not found!");
					
					log("Moved "+commands[1]+" from"+ " ("+coords[0]+","+coords[1]+") to "+commands[3]+"."  );
						
					} catch (NumberFormatException e) {
						print("invalid coordinates!");
					} catch (DataFormatException e) {
						print(e.getMessage());
					}
				}
				else
					print("invalid input >:[");
			}
			else
				print("invalid input >:[");
	}
	
}
